package com.xhwl.logistics.service.impl.http;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.common.exception.ApplicationException;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.utils.StringUtils;
import com.xhwl.common.vo.cent.vehicle.CarVO;
import com.xhwl.logistics.bo.cent.VehicleIntegratedConfigBO;
import com.xhwl.logistics.constant.ChuangXiangConstant;
import com.xhwl.logistics.dto.http.*;
import com.xhwl.logistics.util.AboutDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import retrofit2.HttpException;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Description： 对接创享http接口调用
 * @Author: hule
 * @Date: 2022/08/18
 */
@Slf4j
//@Service
public class ChuangXiangHttpServiceImpl {

    private static final Integer pageSize = 50;
    private static final Integer pklotNum = 1;
    private static final String visitorCount = "-1";
    private static final Integer payTypeWX = 2;

    /**
     * 创享返回结果判断
     */
    private String chuangXiangResponseHandler(JSONObject resultObject){
        String status = resultObject.getString("status");
        if(StringUtils.equals(status,"0")){
            throw new BusinessException(resultObject.getString("message"));
        }
        return resultObject.getString("Data");
    }

    /**
     * 查询车辆类型
     * @param vehicleIntegratedConfigBO
     * @return
     */
    public List<CardTypeChuangXiangDTO> getParkCarType(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        //该参数是否参与签名的map
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求入参的map
        HashMap<String, Object> params = new HashMap<>();
        params.put("appKey", vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey", false);
        params.put("parkingId", vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId", true);
        params.put("timestamp", new Date().getTime());
        isSign.put("timestamp", true);
        params.put("sign", getSign(getSortedParam(params, isSign), vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_GET_CAR_TYPE, params);
        return JSONObject.parseArray(chuangXiangResponseHandler(resultObject),CardTypeChuangXiangDTO.class);
    }

    /**
     * 查看车场信息
     */
    public ParkingLotInfoChuangXiangDTO getParkingLotInfo(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_GET_PARKINGLOT_INFO, params);
        return JSONObject.parseObject(chuangXiangResponseHandler(resultObject),ParkingLotInfoChuangXiangDTO.class);
    }

    /**
     * 查看通道信息
     */
    public List<ParkingLotPassageChuangXiangDTO> getPassageInfo(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_GET_PASSAGE_INFO,
                params);
        return JSONObject.parseArray(chuangXiangResponseHandler(resultObject),ParkingLotPassageChuangXiangDTO.class);
    }

    /**
     * 查看设备和设备状态
     */
    public JSONArray getDeviceStatusInfo(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_GET_DEVICE_STATUS_INFO,
                params);
        return JSONObject.parseArray(chuangXiangResponseHandler(resultObject));
    }

    /**
     * 获取车场车位信息
     */
    public CarportChuangXiangDTO getParkingCarspotInfo(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_GET_PARKING_CARSPOT_INFO,
                params);
        return JSONObject.parseObject(chuangXiangResponseHandler(resultObject),CarportChuangXiangDTO.class);
    }

    /**
     * 获取车场中所有的月租卡车信息
     */
    public List<CarMonthInfoChuangXiangDTO> getParkingMonthCarInfo(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        List<CarMonthInfoChuangXiangDTO> carMonthInfoChuangXiangDTOS = new LinkedList<>();
        Integer pageNum = 1;
        List<CarMonthInfoChuangXiangDTO> records = null;
        do {
            records = getParkingMonthCarInfoPage(vehicleIntegratedConfigBO,pageNum);
            if(CollectionUtils.isEmpty(records)){
                break;
            }
            carMonthInfoChuangXiangDTOS.addAll(records);
            ++pageNum;
        }while (!CollectionUtils.isEmpty(records)&&records.size()==50);
        return carMonthInfoChuangXiangDTOS;
    }

    /**
     * 分页获取车场中的月租卡车信息
     */
    private List<CarMonthInfoChuangXiangDTO> getParkingMonthCarInfoPage(VehicleIntegratedConfigBO vehicleIntegratedConfigBO,Integer pageIndex){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("pageIndex",pageIndex);
        isSign.put("pageIndex",true);
        params.put("pageSize",pageSize);
        isSign.put("pageSize",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_GET_MONTH_CAR_INFO,
                params);
        return JSONObject.parseArray(chuangXiangResponseHandler(resultObject), CarMonthInfoChuangXiangDTO.class);
    }

    /**
     * 对接创享，控制道闸开关
     */
    public void controlDevice(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, String gateId, Integer status){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("gateId",gateId);
        isSign.put("gateId",true);
        params.put("status",status);
        isSign.put("status",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_CONTROL_DEVICE,
                params);
        chuangXiangResponseHandler(resultObject);
    }

    /**
     * 对接创享，获取车型信息
     */
    public JSONArray getCarTypeInfo(VehicleIntegratedConfigBO vehicleIntegratedConfigBO){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_CAR_TYPE_INFO,
                params);
        return JSONObject.parseArray(chuangXiangResponseHandler(resultObject));
    }

    /**
     * 对接创享，新增或修改月租
     */
    public void addOrUpdateMonthCar(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, String ownerName, String ownerPhone,
                                    String plateNumber, String carTypeId, String carModelId, String startTime, String endTime){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("empName", ownerName);
        isSign.put("empName", true);
        params.put("empMoblie", ownerPhone);
        isSign.put("empMoblie", true);
        params.put("plateNumber", plateNumber);
        isSign.put("plateNumber", true);
        params.put("carTypeId", carTypeId);
        isSign.put("carTypeId", true);
        params.put("carModelId", carModelId);
        isSign.put("carModelId", true);
        params.put("startTime", startTime);
        isSign.put("startTime", true);
        params.put("endTime", endTime);
        isSign.put("endTime", true);
        params.put("pklotNum", pklotNum);
        isSign.put("pklotNum", false);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_ADD_OR_UPDATE_MONTH_CAR,
                params);
        chuangXiangResponseHandler(resultObject);
    }

    /**
     * 删除月租车
     */
    public void deleteMonthCar(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, String plateNumber){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("plateNumber", plateNumber);
        isSign.put("plateNumber", true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_DELETE_MONTH_CAR,
                params);
        chuangXiangResponseHandler(resultObject);
    }

    /**
     * 对接创享，添加访客
     */
    public void reserveCar(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, CarVO carVO, String carModelId){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("plateNumber", carVO.getPlateNumber());
        isSign.put("plateNumber", true);
        params.put("visitorName", carVO.getOwnerName());
        isSign.put("visitorName", true);
        params.put("mobilePhone", carVO.getOwnerPhone());
        isSign.put("mobilePhone", false);
        params.put("beginTime", AboutDateUtil.dateToString(carVO.getValidBeginTime()));
        isSign.put("beginTime", true);
        params.put("endTime", AboutDateUtil.dateToString(carVO.getValidEndTime()));
        isSign.put("endTime", true);
        params.put("visitorCount", visitorCount);
        isSign.put("visitorCount", true);
        params.put("carModelId", carModelId);
        isSign.put("carModelId", true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign",getSign(getSortedParam(params,isSign),vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_RESERVE_CAR,
                params);
        chuangXiangResponseHandler(resultObject);
    }

    /**
     * 对接创享，月卡续期
     * 暂时无法测试
     */
    public void chargeMonthCar(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, JSONObject reqData, String plateNumber, Date startTime){
        //判断参数是否需要参与签名
        HashMap<String, Boolean> isSign = new HashMap<>();
        //请求的参数
        HashMap<String, Object> params = new HashMap<>();
        params.put("parkingId",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getParkId());
        isSign.put("parkingId",true);
        params.put("plateNumber", plateNumber);
        isSign.put("plateNumber", true);
        params.put("startTime", AboutDateUtil.dateToString(startTime));
        isSign.put("startTime", true);
        params.put("endTime", AboutDateUtil.dateToString(reqData.getDate("endTime")));
        isSign.put("endTime", true);
        params.put("amount", String.valueOf(reqData.getDouble("amount")));
        isSign.put("amount", true);
        params.put("payType", payTypeWX);
        isSign.put("payType", true);
        params.put("timestamp",new Date().getTime());
        isSign.put("timestamp",true);
        params.put("appKey",vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId());
        isSign.put("appKey",false);
        params.put("sign", getSign(getSortedParam(params, isSign), vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getAppId()));
        JSONObject resultObject = post(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getHost() + ChuangXiangConstant.VEHICLE_MONTH_CAR_RENEW,
                params);
        chuangXiangResponseHandler(resultObject);
    }

    /**
     * 对params的map进行key排序，拼接成降序string
     * @param params
     * @return
     */
    private String getSortedParam(HashMap<String, Object> params, HashMap<String, Boolean> isSign){
        StringBuilder paramStr = new StringBuilder();
        List<String> keySortList = new ArrayList<>(params.keySet());
        keySortList.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        for (String key : keySortList){
            if (isSign.get(key)){
                paramStr.append(key).append("=").append(params.get(key)).append("&");
            }
        }
        return paramStr.substring(0, paramStr.length() - 1);
    }

    /**
     * post请求创享接口
     * @param path
     * @param params
     * @return
     */
    private JSONObject post(String path, Map<String, Object> params){
        log.info("【ChuangXiang post】path:{};params:{}", path, JSON.toJSONString(params));
        String result = null;
        try{
            result = HttpRequest
                    .post(path)
                    .body(JSON.toJSONString(params))
                    .execute()
                    .body();
        }catch (HttpException e){
            log.error("【ChuangXiang post】path:{};params:{}; request failed!", path, JSON.toJSONString(params));
            e.printStackTrace();
            throw new ApplicationException();
        }
        if (StringUtils.isEmpty(result)) {
            log.error("【ChuangXiang post】path:{};params:{};result is null!", path, JSON.toJSONString(params));
            throw new BusinessException();
        }
        log.info("【ChuangXiang post】path:{};params:{};result:{}", path, JSON.toJSONString(params), result);
        return JSON.parseObject(result);
    }

    /**
     * 获取签名
     * @param param
     * @param appKey
     * @return
     */
    private String getSign(String param, String appKey){
        String preSign = param + appKey;
        return DigestUtils.md5DigestAsHex(preSign.getBytes(StandardCharsets.UTF_8)).toUpperCase();
    }

}
